#include "stdafx.h"
#include "SelectRule.h"
#include "CombatCard.h"
#include <algorithm>

struct  SelectRuleDefReflectionRegister
{
	SelectRuleDefReflectionRegister()
	{
		REGISTER_REFLECTION_MEMBER(SelectRule,m_iID,0).Editor_SetAsPrimaryKey();
		REGISTER_REFLECTION_MEMBER(SelectRule,m_sDisplayName,std::string("DefaultName")).Editor_SetAsDisplayName();
		REGISTER_REFLECTION_MEMBER(SelectRule,m_iNum,(uint32)1).Editor_SetAsRaw();
		REGISTER_REFLECTION_MEMBER(SelectRule,m_eSortby,ERuleSort_None).Editor_SetAsEnumation<ERuleSort>();
		REGISTER_REFLECTION_MEMBER(SelectRule,m_eOrder,ERuleSelectOrder_Top).Editor_SetAsEnumation<ERuleSelectOrder>();

		GlobalClassManager::Instance().RegisterClass(SelectRule::s_GetReflection(),eDefaultDef_SelectRules);
		GlobalDefManager::Instance().RegisterDefManger(&SelectRuleManager::Instance());

	}
}__selectruledefreflectionregister;

static bool CompareHPLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	return pObjA->GetHp()<pObjB->GetHp();
}
static bool CompareCDLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;

	return ((CombatCard*)pObjA)->GetCurCD()<((CombatCard*)pObjB)->GetCurCD();
}
static bool CompareAtkLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;

	return ((CombatCard*)pObjA)->GetAtk()<((CombatCard*)pObjB)->GetAtk();
}
static bool CompareHPLoseAbsLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;

	return (pObjA->GetHpMax()-pObjA->GetHp())<(pObjB->GetHpMax()-pObjB->GetHp());
}
static bool CompareHPPercentLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;

	return pObjA->GetHp()/pObjA->GetHpMax() < pObjB->GetHp()/pObjB->GetHpMax();
}
static bool CompareHPMaxLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;

	return ((CombatCard*)pObjA)->GetHpMax()<((CombatCard*)pObjB)->GetHpMax();
}
static bool CompareStarLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;
	const CardDef * pDefA=((CombatCard*)pObjA)->GetDef();
	const CardDef * pDefB=((CombatCard*)pObjB)->GetDef();
	if(pDefA&&pDefB)
	{
		return pDefA->m_pCardType->m_iStar <pDefB->m_pCardType->m_iStar;
	}
	else
		return false;
}
static bool CompareCostLessThan(CombatObj* pObjA,CombatObj* pObjB)
{
	if(pObjA->GetObjType()!=ECombatObj_Card || pObjB->GetObjType()!=ECombatObj_Card) return false;
	const CardDef * pDefA=((CombatCard*)pObjA)->GetDef();
	const CardDef * pDefB=((CombatCard*)pObjB)->GetDef();
	if(pDefA&&pDefB)
	{
		return pDefA->m_pCardType->m_iCost <pDefB->m_pCardType->m_iCost;
	}
	else
		return false;
	
}

static bool __CompareByLocation(const CombatObj* pA,const CombatObj* pB)
{
	if(pA->GetObjType()==ECombatObj_Card && pB->GetObjType()==ECombatObj_Card)
	{
		return ((const CombatCard*)pA)->GetLocation() < ((const CombatCard*)pB)->GetLocation();
	}
	return false;
}
void SelectRule::ApplyRule( std::vector<CombatObj*>& vInputs ) const
{
	switch(m_eSortby)
	{
		case ERuleSort_Hp:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareHPLessThan);
			}break;
		case ERuleSort_CD:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareCDLessThan);
			}break;
		case ERuleSort_ATK:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareAtkLessThan);
			}break;
		case ERuleSort_HPLoseAbs:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareHPLoseAbsLessThan);
			}break;
		case ERuleSort_HPPercent:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareHPPercentLessThan);
			}break;
		case ERuleSort_HPMax:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareHPMaxLessThan);
			}break;
		case ERuleSort_Star:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareStarLessThan);
			}break;
		case ERuleSort_Cost:
			{
				std::sort(vInputs.begin(),vInputs.end(),CompareCostLessThan);
			}break;
	};

	if(m_iNum<vInputs.size())
	{
		switch(m_eOrder)
		{
		case ERuleSelectOrder_Top:
			{
				vInputs.erase(vInputs.begin()+m_iNum,vInputs.end());
			}break;
		case ERuleSelectOrder_Tail:
			{
				vInputs.erase(vInputs.begin(),vInputs.begin()+(vInputs.size()-m_iNum));

			}break;
		case ERuleSelectOrder_Random:
			{
				uint32 iDelNum=vInputs.size()-m_iNum;
				for(uint32 ii=0;ii<iDelNum;ii++)
				{
					uint32 iDel=rand()%vInputs.size();
					vInputs.erase(vInputs.begin()+iDel);
				}
			}break;
		}
	}//if(m_iNum<vInputs.size())

	std::sort(vInputs.begin(),vInputs.end(),__CompareByLocation);
}
